/*
 * Msg.cpp
 *
 *  Created on: 2013. 7. 22.
 *      Author: jjaehuny
 */

#include <Dispatcher/Static.h>
#include <Database/Static.h>
#include "ChannelServer.h"
#include "User.h"

#include <map>
#include <vector>
#include <memory>

#include "Static.h"

namespace CacheServer {

void Msg::SendFailUserInfo(ChannelServer * pChannelServer, uint32_t seq, CacheResult result, const char * strError)
{
	UserInfoAck ack;
	ack.seq = seq;
	ack.result = result;
	ack.strError = strError;
	pChannelServer->SendMsg(ack);
}

void Msg::SendFailCharacterInfo(ChannelServer * pChannelServer, uint32_t seq, CacheResult result, const char * strError)
{
	CharacterInfoAck ack;
	ack.seq = seq;
	ack.result = result;
	ack.strError = strError;
	pChannelServer->SendMsg(ack);
}

void Msg::SendFailFlushCharacterInfo(ChannelServer * pChannelServer, uint32_t seq, CacheResult result, const char * strError)
{
	FlushCharacterInfoAck ack;
	ack.seq = seq;
	ack.result = result;
	ack.strError = strError;
	pChannelServer->SendMsg(ack);
}

void Msg::SendFailFlushUserInfo(ChannelServer * pChannelServer, uint32_t seq, CacheResult result, const char * strError)
{
	FlushUserInfoAck ack;
	ack.seq = seq;
	ack.result = result;
	ack.strError = strError;
	pChannelServer->SendMsg(ack);
}

void Msg::SendFlushUserSlotInfo(ChannelServer * pChannelServer, uint32_t seq, uint32_t slotIndex, CacheResult result, const char * strError)
{
	FlushUserSlotInfoAck ack;
	ack.seq = seq;
	ack.slotIndex = slotIndex;
	ack.result = result;
	ack.strError = strError;

	pChannelServer->SendMsg(ack);
}

void
Msg::OnUserInfoSyn(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	UserInfoSyn syn;
	pPacket->Read(syn);
	//LOG(DEV, "OnUserInfoSyn seq : ", syn.seq );

	int mod = syn.seq % s_Mode;
	MAP & clsMap = Static::Instance().s_clsTreeVector[mod];//s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);
	if (clsMap.end() == itr)
	{
		//LOG(DEV, "OnUserInfoSyn not found user userkey : ", syn.seq );

		std::shared_ptr<User> clsuser = Static::Instance().clsUserPool.Create();
		clsuser->Initialize(pchannelserver->GetChannelKey());

		Database::ResultSet res = Database::Execute(1, "call sp_select_info_user(", syn.seq, ")");
		//Database::ResultSet res = Database::Execute(1, "SELECT * FROM userinfo WHERE user_seq = ", syn.seq, ";");
		if (0 != res.GetSQLError())
		{
			LOG(DEV, "OnUserInfoSyn errno : ", errno );
			SendFailUserInfo(pchannelserver, syn.seq, CACHE_DATABASE_ERROR, "sql error");
			return;
		}

		if (res.end() == res.begin())
		{
			LOG(DEV, "OnUserInfoSyn result is null" );
			SendFailUserInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_USER, "result set is zero");
			return;
		}


		int idx = 1;
		int slotIndex = 0;
		for(Database::ResultSet::iterator itr = res.begin(); itr != res.end(); itr++)
		{
			int seq = itr->getInt(idx++);
			clsuser->GetUserInfo().userseq = itr->getInt(idx++);

			for (int i = 0; i < 8; i++)
			{
				slot clsSlot;
				clsSlot.open = itr->getBoolean(idx++);
				clsSlot.character_seq = itr->getInt(idx++);
				clsSlot.makeCharacter = itr->getInt(idx++);
				clsSlot.remainStatResetCount = itr->getInt(idx++);
				clsSlot.classtype = itr->getInt(idx++);
				clsSlot.level = itr->getInt(idx++);
				//clsSlot.reg_date = itr->getString(idx++);
				clsSlot.reg_date = itr->getUInt64(idx++);

				clsuser->GetUserInfo().array_Slot[slotIndex] = clsSlot;
				slotIndex++;

				User::Character clsCharacter;
				clsCharacter._bOpen = clsSlot.open;
				clsCharacter._bLoad = false;
				clsCharacter._char_seq = clsSlot.character_seq;
				clsuser->_char_tree[clsCharacter._char_seq] = clsCharacter;
			}

			//clsuser->GetUserInfo().zen = itr->getInt(idx++);
			int zen = itr->getInt(idx++);
			clsuser->GetUserInfo().main_slot_index = itr->getInt(idx++);
			clsuser->GetUserInfo().nickname = itr->getString(idx++);
			clsuser->GetUserInfo().profile_url = itr->getString(idx++);
			clsuser->GetUserInfo().score = itr->getInt(idx++);
			clsuser->GetUserInfo().heart_blocked = itr->getInt(idx++);
			clsuser->GetUserInfo().invite_blocked = itr->getInt(idx++);
			clsuser->GetUserInfo().profile_opened = itr->getInt(idx++);
			clsuser->GetUserInfo().company		  = itr->getInt(idx++);
			clsuser->GetUserInfo().sale_code	  = itr->getInt(idx++);
			clsuser->GetUserInfo().u8intro_state	= itr->getInt(idx++);
			clsuser->GetUserInfo().wp_last_week		= itr->getInt(idx++);
			clsuser->GetUserInfo().wp_cur_week		= itr->getInt(idx++);
			clsuser->GetUserInfo().wp_reg_date		= itr->getUInt64(idx++);

			for (int i = 0; i < 4; i++)
			{
				clsuser->GetUserInfo().array_tutorial[i] = itr->getInt(idx++);
			}

			clsuser->GetUserInfo().uuid = itr->getString(idx++);
			clsuser->GetUserInfo().battle_aftereffect_time = itr->getInt(idx++);
			clsuser->GetUserInfo().reward = itr->getString(idx++);
			clsuser->GetUserInfo().shard_Item_db_type = itr->getInt(idx++);
			clsuser->GetUserInfo().wp_last_reg_date = itr->getUInt64(idx++);

			clsuser->GetUserInfo().reserve1 = itr->getUInt64(idx++);
			clsuser->GetUserInfo().reserve2 = itr->getUInt64(idx++);
			clsuser->GetUserInfo().reserve3 = itr->getUInt64(idx++);
			clsuser->GetUserInfo().reserve4 = itr->getUInt64(idx++);
			clsuser->GetUserInfo().reserve5 = itr->getUInt64(idx++);

			clsuser->GetUserInfo().worldboss_hit = itr->getUInt64(idx++);
			clsuser->GetUserInfo().worldboss_point = itr->getUInt64(idx++);

			clsuser->GetUserInfo().medal = itr->getString(idx++);
			clsuser->GetUserInfo().recv_stamina = itr->getInt(idx++);
			clsuser->GetUserInfo().recv_stamina_time = itr->getUInt64(idx++);
			clsuser->GetUserInfo().guild_seq = itr->getInt(idx++);
		}

		LOG(DEV, "OnUserInfoSyn seq : ", syn.seq, " Send Select Data");

		UserInfoAck ack;
		ack.seq = syn.seq;
		ack.result = CACHE_SUCCESS;
		ack.stUserInfo = clsuser->GetUserInfo();

		pchannelserver->SendMsg(ack);
		clsuser->KillTimer();

		clsMap[syn.seq] = clsuser;

		return;
	}

	LOG(DEV, "OnUserInfoSyn seq : ", syn.seq, " Send cache Data");
	std::shared_ptr<User> clsuser = (* itr).second;

	UserInfoAck ack;
	ack.seq = syn.seq;
	ack.result = CACHE_SUCCESS;
	ack.stUserInfo = clsuser->GetUserInfo();

	pchannelserver->SendMsg(ack);

	clsuser->KillTimer();
}

void
Msg::OnCharacterInfoSyn(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	CharacterInfoSyn syn;
	pPacket->Read(syn);
	//LOG(DEV, "OnCharacterInfoSyn seq : ", syn.seq, " char seq :", syn.char_seq);

	int mod = syn.seq % s_Mode;
	MAP & clsMap = Static::Instance().s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);

	// not found user
	if (clsMap.end() == itr)
	{
		LOG(DEV, "OnCharacterInfoSyn seq : ", syn.seq, " not found user");
		SendFailCharacterInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_USER, "not found user");
		return;
	}

	std::shared_ptr<User> clsuser = (* itr).second;

	std::map<uint32_t, User::Character>::iterator citr = clsuser->_char_tree.find(syn.char_seq);
	if (clsuser->_char_tree.end() == citr)
	{
		LOG(DEV, "OnCharacterInfoSyn seq : ", syn.seq, "not found character");
		SendFailCharacterInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_CHARACTER, "not found character");
		return;
	}

	if (false == citr->second._bLoad)
	{
		// load  charinfo
		Database::ResultSet res = Database::Execute(1, "call sp_select_info_character(", syn.char_seq, ")");
		//Database::ResultSet res = Database::Execute(1, "SELECT * FROM characterinfo WHERE seq = ", syn.char_seq, ";");

		if (0 != res.GetSQLError())
		{
			LOG(DEV, "OnCharacterInfoSyn errno : ", errno );
			SendFailUserInfo(pchannelserver, syn.seq, CACHE_DATABASE_ERROR, "sql error");
			return;
		}

		if (res.end() == res.begin())
		{
			LOG(DEV, "OnUserInfoSyn result is null" );
			SendFailUserInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_CHARACTER, "result set is zero");
			return;
		}

		int idx = 1;
		for(Database::ResultSet::iterator itr = res.begin(); itr != res.end(); itr++)
		{
			citr->second._characterInfo.characterseq = itr->getInt(idx++);
			citr->second._characterInfo.userSeq = itr->getInt(idx++);

			citr->second._characterInfo.slotindex = itr->getInt(idx++);
			citr->second._characterInfo.classtype = itr->getInt(idx++);
			citr->second._characterInfo.remain_stat_point = itr->getInt(idx++);
			citr->second._characterInfo.remain_skill_point = itr->getInt(idx++);
			citr->second._characterInfo.ap_current = itr->getInt(idx++);
			citr->second._characterInfo.ep_current = itr->getInt(idx++);
			citr->second._characterInfo.ep_max = itr->getInt(idx++);

			citr->second._characterInfo.weapon = itr->getUInt64(idx++);
			citr->second._characterInfo.weapon_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.helmet = itr->getUInt64(idx++);
			citr->second._characterInfo.helmet_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.armor = itr->getUInt64(idx++);
			citr->second._characterInfo.armor_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.glove = itr->getUInt64(idx++);
			citr->second._characterInfo.shoes = itr->getUInt64(idx++);
			citr->second._characterInfo.necklace = itr->getUInt64(idx++);
			citr->second._characterInfo.cloak = itr->getUInt64(idx++);
			citr->second._characterInfo.ring = itr->getUInt64(idx++);
			citr->second._characterInfo.charm = itr->getUInt64(idx++);
			citr->second._characterInfo.avartar = itr->getUInt64(idx++);
			citr->second._characterInfo.avartar_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.vehicle = itr->getUInt64(idx++);
			citr->second._characterInfo.vehicle_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.title = itr->getUInt64(idx++);
			citr->second._characterInfo.fairy = itr->getUInt64(idx++);
			citr->second._characterInfo.battlepet = itr->getUInt64(idx++);

			citr->second._characterInfo.exp = itr->getInt(idx++);

			citr->second._characterInfo.level = itr->getInt(idx++);
			citr->second._characterInfo.str = itr->getInt(idx++);
			citr->second._characterInfo.dex = itr->getInt(idx++);
			citr->second._characterInfo.con = itr->getInt(idx++);
			citr->second._characterInfo.spi = itr->getInt(idx++);


			for (int i = 0; i < 8; i++)
			{
				QuickSlot clsQuickSlot;
				clsQuickSlot.type = itr->getInt(idx++);
				clsQuickSlot.index = itr->getUInt64(idx++);

				citr->second._characterInfo.array_QuickSlot[i] = clsQuickSlot;
			}

			for (int i = 0; i < 20; i++)
			{
				citr->second._characterInfo.array_Skill[i] = itr->getInt(idx++);
			}

			citr->second._characterInfo.gold = itr->getInt(idx++);

//			for (int i = 0; i < 4; i++)
//			{
//				citr->second._characterInfo.array_tutorial[i] = itr->getInt(idx++);
//			}

			citr->second._characterInfo.event_stamina = itr->getInt(idx++);
			citr->second._characterInfo.recover_stamina_sec = itr->getUInt64(idx++);

			citr->second._characterInfo.drill_status = itr->getInt(idx++);
			citr->second._characterInfo.drill_time = itr->getInt(idx++);
			citr->second._characterInfo.drill_start = itr->getUInt64(idx++);
			citr->second._characterInfo.drill_end = itr->getUInt64(idx++);

			citr->second._characterInfo.consecutive_win = itr->getInt(idx++);
			citr->second._characterInfo.win_comment = itr->getString(idx++);

			citr->second._characterInfo.reg_date = itr->getUInt64(idx++);

			citr->second._characterInfo.dungeon_clear_info = itr->getString(idx++);
			citr->second._characterInfo.bag_order_info = itr->getString(idx++);
			citr->second._characterInfo.buff_info = itr->getString(idx++);
			citr->second._characterInfo.battle_afterEffect_info = itr->getString(idx++);

			citr->second._characterInfo.daily_ep = itr->getInt(idx++);

			int idDelete = 0;
			int64_t deleteDate = 0;

			idDelete = itr->getInt(idx++);
			deleteDate = itr->getUInt64(idx++);

			citr->second._characterInfo.name_tag = itr->getUInt64(idx++);
			citr->second._characterInfo.name_tag_iconidx = itr->getInt(idx++);

			citr->second._characterInfo.reserve1 = itr->getUInt64(idx++);
			citr->second._characterInfo.reserve2 = itr->getUInt64(idx++);
			citr->second._characterInfo.reserve3 = itr->getUInt64(idx++);
			citr->second._characterInfo.reserve4 = itr->getUInt64(idx++);
			citr->second._characterInfo.reserve5 = itr->getUInt64(idx++);
			citr->second._characterInfo.daily_mission_info = itr->getString(idx++);
			citr->second._characterInfo.cur_stamina = itr->getInt(idx++);
			citr->second._characterInfo.max_stamina = itr->getInt(idx++);
		}

		citr->second._bLoad = true;
		citr->second._char_seq = syn.char_seq;

		//LOG(DEV, "OnCharacterInfoSyn seq : ", syn.seq, " Send Select Data");

		CharacterInfoAck ack;
		ack.seq = syn.seq;
		ack.result = CACHE_SUCCESS;
		ack.stCharacterInfo = citr->second._characterInfo;
		pchannelserver->SendMsg(ack);

		return;
	}

	//LOG(DEV, "OnCharacterInfoSyn seq : ", syn.seq, " Send cache Data");
	CharacterInfoAck ack;
	ack.seq = syn.seq;
	ack.result = CACHE_SUCCESS;
	ack.stCharacterInfo = citr->second._characterInfo;
	pchannelserver->SendMsg(ack);
}

void
Msg::OnFlushCharacterInfoSyn(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	FlushCharacterInfoSyn syn;
	pPacket->Read(syn);
	//LOG(DEV, "OnFlushCharacterInfoSyn seq : ", syn.seq, "char seq :", syn.char_seq);

	int mod = syn.seq % s_Mode;
	MAP & clsMap = Static::Instance().s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);

	// not found user
	if (clsMap.end() == itr)
	{
		LOG(DEV, "OnFlushCharacterInfoSyn seq : ", syn.seq, " not found user");
		SendFailFlushCharacterInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_USER, "not found user");
		return;
	}

	//LOG(DEV, "OnFlushCharacterInfoSyn found user seq : ", syn.seq );
	std::shared_ptr<User> clsuser = (* itr).second;

	std::map<uint32_t, User::Character>::iterator citr = clsuser->_char_tree.find(syn.char_seq);
	if (clsuser->_char_tree.end() == citr)
	{
		LOG(DEV, "OnFlushCharacterInfoSyn seq : ", syn.seq, "not found character");
		SendFailFlushCharacterInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_CHARACTER, "not found character");
		return;
	}

	clsuser->_char_tree[syn.char_seq]._characterInfo = syn.stCharacterInfo;

	if (false == syn.flushDB)
	{
		SendFailFlushCharacterInfo(pchannelserver, syn.seq, CACHE_SUCCESS, "success");
		return;
	}

	// load  charinfo
	Database::ResultSet res = Database::Execute(1, "call sp_update_info_character(",
			syn.stCharacterInfo.classtype , "," ,
			syn.stCharacterInfo.remain_stat_point , "," ,
			syn.stCharacterInfo.remain_skill_point , "," ,
			syn.stCharacterInfo.ap_current , "," ,
			syn.stCharacterInfo.ep_current , "," ,
			syn.stCharacterInfo.ep_max , "," ,
			syn.stCharacterInfo.weapon , "," ,
			syn.stCharacterInfo.weapon_iconidx , "," ,
			syn.stCharacterInfo.helmet , "," ,
			syn.stCharacterInfo.helmet_iconidx , "," ,
			syn.stCharacterInfo.armor , "," ,
			syn.stCharacterInfo.armor_iconidx , "," ,
			syn.stCharacterInfo.glove , "," ,
			syn.stCharacterInfo.shoes , "," ,
			syn.stCharacterInfo.necklace , "," ,
			syn.stCharacterInfo.cloak , "," ,
			syn.stCharacterInfo.ring , "," ,
			syn.stCharacterInfo.charm , "," ,
			syn.stCharacterInfo.avartar , "," ,
			syn.stCharacterInfo.avartar_iconidx , "," ,
			syn.stCharacterInfo.vehicle , "," ,
			syn.stCharacterInfo.vehicle_iconidx , "," ,
			syn.stCharacterInfo.title , "," ,
			syn.stCharacterInfo.fairy , "," ,
			syn.stCharacterInfo.battlepet , "," ,
			syn.stCharacterInfo.exp  , "," ,
			syn.stCharacterInfo.level , "," ,
			syn.stCharacterInfo.str, "," ,
			syn.stCharacterInfo.dex , "," ,
			syn.stCharacterInfo.con , "," ,
			syn.stCharacterInfo.spi , "," ,
			syn.stCharacterInfo.array_QuickSlot[0].type , "," ,
			syn.stCharacterInfo.array_QuickSlot[0].index , "," ,
			syn.stCharacterInfo.array_QuickSlot[1].type , "," ,
			syn.stCharacterInfo.array_QuickSlot[1].index , "," ,
			syn.stCharacterInfo.array_QuickSlot[2].type , "," ,
			syn.stCharacterInfo.array_QuickSlot[2].index , "," ,
			syn.stCharacterInfo.array_QuickSlot[3].type , "," ,
			syn.stCharacterInfo.array_QuickSlot[3].index , "," ,
			syn.stCharacterInfo.array_QuickSlot[4].type , "," ,
			syn.stCharacterInfo.array_QuickSlot[4].index , "," ,
			syn.stCharacterInfo.array_QuickSlot[5].type , "," ,
			syn.stCharacterInfo.array_QuickSlot[5].index , "," ,
			syn.stCharacterInfo.array_QuickSlot[6].type , "," ,
			syn.stCharacterInfo.array_QuickSlot[6].index , "," ,
			syn.stCharacterInfo.array_QuickSlot[7].type , "," ,
			syn.stCharacterInfo.array_QuickSlot[7].index , "," ,
			syn.stCharacterInfo.array_Skill[0] , "," ,
			syn.stCharacterInfo.array_Skill[1] , "," ,
			syn.stCharacterInfo.array_Skill[2] , "," ,
			syn.stCharacterInfo.array_Skill[3] , "," ,
			syn.stCharacterInfo.array_Skill[4] , "," ,
			syn.stCharacterInfo.array_Skill[5] , "," ,
			syn.stCharacterInfo.array_Skill[6] , "," ,
			syn.stCharacterInfo.array_Skill[7] , "," ,
			syn.stCharacterInfo.array_Skill[8] , "," ,
			syn.stCharacterInfo.array_Skill[9] , "," ,
			syn.stCharacterInfo.array_Skill[10] , "," ,
			syn.stCharacterInfo.array_Skill[11] , "," ,
			syn.stCharacterInfo.array_Skill[12] , "," ,
			syn.stCharacterInfo.array_Skill[13] , "," ,
			syn.stCharacterInfo.array_Skill[14] , "," ,
			syn.stCharacterInfo.array_Skill[15] , "," ,
			syn.stCharacterInfo.array_Skill[16] , "," ,
			syn.stCharacterInfo.array_Skill[17] , "," ,
			syn.stCharacterInfo.array_Skill[18] , "," ,
			syn.stCharacterInfo.array_Skill[19] , "," ,
			syn.stCharacterInfo.gold , "," ,
//			syn.stCharacterInfo.array_tutorial[0] , "," ,
//			syn.stCharacterInfo.array_tutorial[1] , "," ,
//			syn.stCharacterInfo.array_tutorial[2] , "," ,
//			syn.stCharacterInfo.array_tutorial[3] , "," ,
			syn.stCharacterInfo.event_stamina , "," ,
			syn.stCharacterInfo.recover_stamina_sec , "," ,
			syn.stCharacterInfo.drill_status , "," ,
			syn.stCharacterInfo.drill_time , "," ,
			syn.stCharacterInfo.drill_start , "," ,
			syn.stCharacterInfo.drill_end , "," ,
			syn.stCharacterInfo.consecutive_win , "," ,
			"'", syn.stCharacterInfo.win_comment , "'," ,
			"'", syn.stCharacterInfo.dungeon_clear_info , "'," ,
			"'", syn.stCharacterInfo.bag_order_info , "'," ,
			"'", syn.stCharacterInfo.buff_info , "'," ,
			"'", syn.stCharacterInfo.battle_afterEffect_info , "'," ,
			syn.stCharacterInfo.daily_ep, ",",
			syn.stCharacterInfo.name_tag, ",",
			syn.stCharacterInfo.name_tag_iconidx, ",",
			syn.stCharacterInfo.reserve1, ",",
			syn.stCharacterInfo.reserve2, ",",
			syn.stCharacterInfo.reserve3, ",",
			syn.stCharacterInfo.reserve4, ",",
			syn.stCharacterInfo.reserve5, ",",
			"'", syn.stCharacterInfo.daily_mission_info, "'," ,
			syn.stCharacterInfo.cur_stamina, ",",
			syn.stCharacterInfo.max_stamina, ",",
			syn.char_seq, ")"
		);

	if (0 != res.GetSQLError())
	{
		SendFailFlushCharacterInfo(pchannelserver, syn.seq, CACHE_DATABASE_ERROR, "database update error");
		return;
	}

	LOG(DEV, "OnFlushCharacterInfoSyn found user seq : ", syn.seq );
	SendFailFlushCharacterInfo(pchannelserver, syn.seq, CACHE_SUCCESS, "success");
}

void
Msg::OnFlushUserInfoSyn(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	FlushUserInfoSyn syn;
	pPacket->Read(syn);
	//LOG(DEV, "OnFlushUserInfoSyn seq : ", syn.seq );

	int mod = syn.seq % s_Mode;
	MAP & clsMap = Static::Instance().s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);
	if (clsMap.end() == itr)
	{
		LOG(DEV, "OnFlushUserInfoSyn not found user userkey : ", syn.seq );
		SendFailFlushUserInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_USER, "not found user");
		return;
	}

	//LOG(DEV, "OnFlushUserInfoSyn found user seq : ", syn.seq );
	std::shared_ptr<User> clsuser = (* itr).second;

	clsuser->SetUserInfo(syn.stUserInfo);
	//LOG(DEV, "syn.stUserInfo tutorial 4 : ", syn.stUserInfo.array_tutorial[3] );

	if (false == syn.flushDB)
	{
		SendFailFlushUserInfo(pchannelserver, syn.seq, CACHE_SUCCESS, "success");
		return;
	}

	// load  charinfo
	Database::ResultSet res = Database::Execute(1, "call sp_update_info_user(",
			syn.stUserInfo.array_Slot[0].open, "," ,
			syn.stUserInfo.array_Slot[0].character_seq, "," ,
			syn.stUserInfo.array_Slot[0].makeCharacter, "," ,
			syn.stUserInfo.array_Slot[0].remainStatResetCount, "," ,
			syn.stUserInfo.array_Slot[0].classtype, "," ,
			syn.stUserInfo.array_Slot[0].level, "," ,
			syn.stUserInfo.array_Slot[0].reg_date, "," ,
			syn.stUserInfo.array_Slot[1].open, "," ,
			syn.stUserInfo.array_Slot[1].character_seq, "," ,
			syn.stUserInfo.array_Slot[1].makeCharacter, "," ,
			syn.stUserInfo.array_Slot[1].remainStatResetCount, "," ,
			syn.stUserInfo.array_Slot[1].classtype, "," ,
			syn.stUserInfo.array_Slot[1].level, "," ,
			syn.stUserInfo.array_Slot[1].reg_date, "," ,
			syn.stUserInfo.array_Slot[2].open, "," ,
			syn.stUserInfo.array_Slot[2].character_seq, "," ,
			syn.stUserInfo.array_Slot[2].makeCharacter, "," ,
			syn.stUserInfo.array_Slot[2].remainStatResetCount, "," ,
			syn.stUserInfo.array_Slot[2].classtype, "," ,
			syn.stUserInfo.array_Slot[2].level, "," ,
			syn.stUserInfo.array_Slot[2].reg_date, "," ,
			syn.stUserInfo.array_Slot[3].open, "," ,
			syn.stUserInfo.array_Slot[3].character_seq, "," ,
			syn.stUserInfo.array_Slot[3].makeCharacter, "," ,
			syn.stUserInfo.array_Slot[3].remainStatResetCount, "," ,
			syn.stUserInfo.array_Slot[3].classtype, "," ,
			syn.stUserInfo.array_Slot[3].level, "," ,
			syn.stUserInfo.array_Slot[3].reg_date, "," ,
			syn.stUserInfo.array_Slot[4].open, "," ,
			syn.stUserInfo.array_Slot[4].character_seq, "," ,
			syn.stUserInfo.array_Slot[4].makeCharacter, "," ,
			syn.stUserInfo.array_Slot[4].remainStatResetCount, "," ,
			syn.stUserInfo.array_Slot[4].classtype, "," ,
			syn.stUserInfo.array_Slot[4].level, "," ,
			syn.stUserInfo.array_Slot[4].reg_date, "," ,
			syn.stUserInfo.array_Slot[5].open, "," ,
			syn.stUserInfo.array_Slot[5].character_seq, "," ,
			syn.stUserInfo.array_Slot[5].makeCharacter, "," ,
			syn.stUserInfo.array_Slot[5].remainStatResetCount, "," ,
			syn.stUserInfo.array_Slot[5].classtype, "," ,
			syn.stUserInfo.array_Slot[5].level, "," ,
			syn.stUserInfo.array_Slot[5].reg_date, "," ,
			syn.stUserInfo.array_Slot[6].open, "," ,
			syn.stUserInfo.array_Slot[6].character_seq, "," ,
			syn.stUserInfo.array_Slot[6].makeCharacter, "," ,
			syn.stUserInfo.array_Slot[6].remainStatResetCount, "," ,
			syn.stUserInfo.array_Slot[6].classtype, "," ,
			syn.stUserInfo.array_Slot[6].level, "," ,
			syn.stUserInfo.array_Slot[6].reg_date, "," ,
			syn.stUserInfo.array_Slot[7].open, "," ,
			syn.stUserInfo.array_Slot[7].character_seq, "," ,
			syn.stUserInfo.array_Slot[7].makeCharacter, "," ,
			syn.stUserInfo.array_Slot[7].remainStatResetCount, "," ,
			syn.stUserInfo.array_Slot[7].classtype, "," ,
			syn.stUserInfo.array_Slot[7].level, "," ,
			syn.stUserInfo.array_Slot[7].reg_date, "," ,
			syn.stUserInfo.main_slot_index, "," ,
			"'", syn.stUserInfo.nickname, "','",
			syn.stUserInfo.profile_url, "'," ,
			syn.stUserInfo.score, "," ,
			syn.stUserInfo.heart_blocked, "," ,
			syn.stUserInfo.invite_blocked, "," ,
			syn.stUserInfo.profile_opened, "," ,
			syn.stUserInfo.company, "," ,
			syn.stUserInfo.sale_code, "," ,
			syn.stUserInfo.u8intro_state, "," ,
			syn.stUserInfo.wp_last_week, "," ,
			syn.stUserInfo.wp_cur_week, "," ,
			syn.stUserInfo.wp_reg_date, "," ,
			syn.stUserInfo.array_tutorial[0] , "," ,
			syn.stUserInfo.array_tutorial[1] , "," ,
			syn.stUserInfo.array_tutorial[2] , "," ,
			syn.stUserInfo.array_tutorial[3] , "," ,
			"'", syn.stUserInfo.uuid , "'," ,
			syn.stUserInfo.battle_aftereffect_time , "," ,
			"'", syn.stUserInfo.reward, "',",
			syn.stUserInfo.wp_last_reg_date, "," ,
			syn.stUserInfo.reserve1, ",",
			syn.stUserInfo.reserve2, ",",
			syn.stUserInfo.reserve3, ",",
			syn.stUserInfo.reserve4, ",",
			syn.stUserInfo.reserve5, ",",
			syn.stUserInfo.worldboss_hit, ",",
			syn.stUserInfo.worldboss_point, ",",
			"'", syn.stUserInfo.medal, "',",
			syn.stUserInfo.recv_stamina, ",",
			syn.stUserInfo.recv_stamina_time, ",",
			syn.stUserInfo.guild_seq, ",",
			syn.seq, ")"
		);

	if (0 != res.GetSQLError())
	{
		SendFailFlushUserInfo(pchannelserver, syn.seq, CACHE_DATABASE_ERROR, "database update error");
		return;
	}

	SendFailFlushUserInfo(pchannelserver, syn.seq, CACHE_SUCCESS, "success");

}

void Msg::OnFlushUserSlotInfoSyn(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	FlushUserSlotInfoSyn syn;
	pPacket->Read(syn);
	//LOG(DEV, "OnFlushUserSlotInfoSyn seq : ", syn.seq );

	int mod = syn.seq % s_Mode;
	MAP & clsMap = Static::Instance().s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);
	if (clsMap.end() == itr)
	{
		LOG(DEV, "OnFlushUserSlotInfoSyn not found user userkey : ", syn.seq );
		SendFlushUserSlotInfo(pchannelserver, syn.seq, syn.slotIndex, CACHE_NOT_EXIST_USER, "not found user");
		return;
	}

	//LOG(DEV, "OnFlushUserSlotInfoSyn found user seq : ", syn.seq , "character seq : ", syn.stSlot.character_seq);
	std::shared_ptr<User> clsuser = (* itr).second;

	clsuser->GetUserInfo().array_Slot[syn.slotIndex] = syn.stSlot;


	User::Character clsCharacter;
	clsCharacter._bOpen = true;
	clsCharacter._bLoad = false;
	clsCharacter._char_seq = syn.stSlot.character_seq;

	clsuser->_char_tree[syn.stSlot.character_seq] = clsCharacter;

	SendFlushUserSlotInfo(pchannelserver, syn.seq, syn.slotIndex, CACHE_SUCCESS, "SUCCESS ");
}

void
Msg::OnRemoveUser(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	RemoveUserSyn syn;
	pPacket->Read(syn);
	LOG(DEV, "OnRemoveUser seq : ", syn.seq);

	int mod = syn.seq % s_Mode;
	//MAP & clsMap = s_clsTreeVector[mod];
	MAP & clsMap = Static::Instance().s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);
	if (clsMap.end() == itr)
	{
		LOG(DEV, "OnRemoveUser not found user userkey : ", syn.seq );

		UserInfoAck ack;
		ack.seq = syn.seq;
		ack.result = CACHE_NOT_EXIST_USER;
		ack.strError = "CACHE_NOT_EXIST_USER";
		pchannelserver->SendMsg(ack);

		return;
	}

	std::shared_ptr<User> clsuser = (* itr).second;
	LOG(DEV, "OnRemoveUser found user seq : ", syn.seq, " bKilled : ", clsuser->GetKilledFlag());

	clsuser->SetTimer();

	RemoveUserAck ack;
	ack.seq = syn.seq;
	ack.result = CACHE_SUCCESS;
	ack.strError = "SUCCESS";
	pchannelserver->SendMsg(ack);
}


void
Msg::OnNewCharacterInfoSyn(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	NewCharacterInfoSyn syn;
	pPacket->Read(syn);
	//LOG(DEV, "OnNewCharacterInfoSyn seq : ", syn.seq, " char seq :", syn.char_seq);

	int mod = syn.seq % s_Mode;
	MAP & clsMap = Static::Instance().s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);

	// not found user
	if (clsMap.end() == itr)
	{
		LOG(DEV, "OnNewCharacterInfoSyn seq : ", syn.seq, " not found user");
		SendFailCharacterInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_USER, "not found user");
		return;
	}

	std::shared_ptr<User> clsuser = (* itr).second;

	std::map<uint32_t, User::Character>::iterator citr = clsuser->_char_tree.find(syn.char_seq);
	if (clsuser->_char_tree.end() == citr)
	{
		LOG(DEV, "OnNewCharacterInfoSyn seq : ", syn.seq, "not found character seq : ", syn.char_seq);
		SendFailCharacterInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_CHARACTER, "not found character");
		return;
	}

	if (false == citr->second._bLoad)
	{
		// load  charinfo
		Database::ResultSet res = Database::Execute(1, "call sp_select_info_character(", syn.char_seq, ")");
		//Database::ResultSet res = Database::Execute(1, "SELECT * FROM characterinfo WHERE seq = ", syn.char_seq, ";");

		if (0 != res.GetSQLError())
		{
			LOG(DEV, "OnNewCharacterInfoSyn errno : ", errno );
			SendFailUserInfo(pchannelserver, syn.seq, CACHE_DATABASE_ERROR, "sql error");
			return;
		}

		if (res.end() == res.begin())
		{
			LOG(DEV, "OnNewCharacterInfoSyn result is null" );
			SendFailUserInfo(pchannelserver, syn.seq, CACHE_NOT_EXIST_CHARACTER, "result set is zero");
			return;
		}

		int idx = 1;
		for(Database::ResultSet::iterator itr = res.begin(); itr != res.end(); itr++)
		{
			citr->second._characterInfo.characterseq = itr->getInt(idx++);
			citr->second._characterInfo.userSeq = itr->getInt(idx++);

			citr->second._characterInfo.slotindex = itr->getInt(idx++);
			citr->second._characterInfo.classtype = itr->getInt(idx++);
			citr->second._characterInfo.remain_stat_point = itr->getInt(idx++);
			citr->second._characterInfo.remain_skill_point = itr->getInt(idx++);
			citr->second._characterInfo.ap_current = itr->getInt(idx++);
			citr->second._characterInfo.ep_current = itr->getInt(idx++);
			citr->second._characterInfo.ep_max = itr->getInt(idx++);

			citr->second._characterInfo.weapon = itr->getUInt64(idx++);
			citr->second._characterInfo.weapon_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.helmet = itr->getUInt64(idx++);
			citr->second._characterInfo.helmet_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.armor = itr->getUInt64(idx++);
			citr->second._characterInfo.armor_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.glove = itr->getUInt64(idx++);
			citr->second._characterInfo.shoes = itr->getUInt64(idx++);
			citr->second._characterInfo.necklace = itr->getUInt64(idx++);
			citr->second._characterInfo.cloak = itr->getUInt64(idx++);
			citr->second._characterInfo.ring = itr->getUInt64(idx++);
			citr->second._characterInfo.charm = itr->getUInt64(idx++);
			citr->second._characterInfo.avartar = itr->getUInt64(idx++);
			citr->second._characterInfo.avartar_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.vehicle = itr->getUInt64(idx++);
			citr->second._characterInfo.vehicle_iconidx = itr->getInt(idx++);
			citr->second._characterInfo.title = itr->getUInt64(idx++);
			citr->second._characterInfo.fairy = itr->getUInt64(idx++);
			citr->second._characterInfo.battlepet = itr->getUInt64(idx++);

			citr->second._characterInfo.exp = itr->getInt(idx++);

			citr->second._characterInfo.level = itr->getInt(idx++);
			citr->second._characterInfo.str = itr->getInt(idx++);
			citr->second._characterInfo.dex = itr->getInt(idx++);
			citr->second._characterInfo.con = itr->getInt(idx++);
			citr->second._characterInfo.spi = itr->getInt(idx++);


			for (int i = 0; i < 8; i++)
			{
				QuickSlot clsQuickSlot;
				clsQuickSlot.type = itr->getInt(idx++);
				clsQuickSlot.index = itr->getInt(idx++);

				citr->second._characterInfo.array_QuickSlot[i] = clsQuickSlot;
			}

			for (int i = 0; i < 20; i++)
			{
				citr->second._characterInfo.array_Skill[i] = itr->getInt(idx++);
			}

			citr->second._characterInfo.gold = itr->getInt(idx++);

//			for (int i = 0; i < 4; i++)
//			{
//				citr->second._characterInfo.array_tutorial[i] = itr->getInt(idx++);
//			}

			citr->second._characterInfo.event_stamina = itr->getInt(idx++);
			citr->second._characterInfo.recover_stamina_sec = itr->getUInt64(idx++);


			citr->second._characterInfo.drill_status = itr->getInt(idx++);
			citr->second._characterInfo.drill_time = itr->getInt(idx++);
			citr->second._characterInfo.drill_start = itr->getUInt64(idx++);
			citr->second._characterInfo.drill_end = itr->getUInt64(idx++);

			citr->second._characterInfo.consecutive_win = itr->getInt(idx++);
			citr->second._characterInfo.win_comment = itr->getString(idx++);

			citr->second._characterInfo.reg_date = itr->getUInt64(idx++);
			citr->second._characterInfo.dungeon_clear_info = itr->getString(idx++);
			citr->second._characterInfo.bag_order_info = itr->getString(idx++);
			citr->second._characterInfo.buff_info = itr->getString(idx++);
			citr->second._characterInfo.battle_afterEffect_info = itr->getString(idx++);

			citr->second._characterInfo.daily_ep = itr->getInt(idx++);

			int idDelete = 0;
			int64_t deleteDate = 0;

			idDelete = itr->getInt(idx++);
			deleteDate = itr->getUInt64(idx++);

			citr->second._characterInfo.name_tag = itr->getUInt64(idx++);
			citr->second._characterInfo.name_tag_iconidx = itr->getInt(idx++);

			citr->second._characterInfo.reserve1 = itr->getUInt64(idx++);
			citr->second._characterInfo.reserve2 = itr->getUInt64(idx++);
			citr->second._characterInfo.reserve3 = itr->getUInt64(idx++);
			citr->second._characterInfo.reserve4 = itr->getUInt64(idx++);
			citr->second._characterInfo.reserve5 = itr->getUInt64(idx++);
			citr->second._characterInfo.daily_mission_info = itr->getString(idx++);
			citr->second._characterInfo.cur_stamina = itr->getInt(idx++);
			citr->second._characterInfo.max_stamina = itr->getInt(idx++);
		}

		citr->second._bLoad = true;
		citr->second._char_seq = syn.char_seq;

		//LOG(DEV, "OnNewCharacterInfoSyn seq : ", syn.seq, " Send Select Data");

		NewCharacterInfoAck ack;
		ack.seq = syn.seq;
		ack.result = CACHE_SUCCESS;
		ack.stCharacterInfo = citr->second._characterInfo;
		pchannelserver->SendMsg(ack);

		return;
	}

	//LOG(DEV, "OnNewCharacterInfoSyn seq : ", syn.seq, " Send cache Data");
	NewCharacterInfoAck ack;
	ack.seq = syn.seq;
	ack.result = CACHE_SUCCESS;
	ack.stCharacterInfo = citr->second._characterInfo;
	pchannelserver->SendMsg(ack);
}

} /* namespace cacheserver */




